home *** CD-ROM | disk | FTP | other *** search
/ Aminet 37 / Aminet 37 (2000)(Schatztruhe)[!][Jun 2000].iso / Aminet / dev / lang / sofa.lha / sofa / smalleiffel / lib_number / number_tools.e < prev    next >
Text File  |  2000-03-25  |  5KB  |  236 lines

  1. -- This file is  free  software, which  comes  along  with  SmallEiffel. This
  2. -- software  is  distributed  in the hope that it will be useful, but WITHOUT 
  3. -- ANY  WARRANTY;  without  even  the  implied warranty of MERCHANTABILITY or
  4. -- FITNESS  FOR A PARTICULAR PURPOSE. You can modify it as you want, provided
  5. -- this header is kept unaltered, and a notification of the changes is added.
  6. -- You  are  allowed  to  redistribute  it and sell it, alone or as a part of 
  7. -- another product.
  8. --          Copyright (C) 1994-98 LORIA - UHP - CRIN - INRIA - FRANCE
  9. --            Dominique COLNET and Suzanne COLLIN - colnet@loria.fr 
  10. --                       http://SmallEiffel.loria.fr
  11. --
  12. expanded class NUMBER_TOOLS
  13. --
  14. -- This clas provides abstract creation functions for NUMBERs.
  15. -- 
  16. -- One may inherit this class in order to use NUMBERs.
  17. -- 
  18.  
  19. feature
  20.  
  21.    is_number(s: STRING): BOOLEAN is
  22.      -- Is `s' the view of some NUMBER ?
  23.       require
  24.      not s.is_empty
  25.       local
  26.      i, state: INTEGER;
  27.      c: CHARACTER;
  28.       do
  29.      from
  30.         i := 1;
  31.         c := s.item(i);
  32.      until
  33.         state > 6 or else i > s.count
  34.      loop
  35.         inspect
  36.            state
  37.         when 0 then     
  38.            -- Waiting optional sign or first digit :
  39.            inspect
  40.           c
  41.            when ' ', '%T' then
  42.            when '+', '-' then
  43.           state := 1;
  44.            when '0' .. '9' then
  45.           state := 2;
  46.            else
  47.           state := 8;
  48.            end;
  49.         when 1 then
  50.                 -- Waiting first digit (sign read) :
  51.            inspect
  52.           c
  53.            when ' ', '%T' then
  54.            when '0' .. '9' then
  55.           state := 2;
  56.            else
  57.           state := 8;
  58.            end;
  59.         when 2 then
  60.            -- Inside integer or numerator :
  61.            inspect
  62.           c
  63.            when ' ', '%T' then
  64.           state := 3;
  65.            when '0' .. '9' then
  66.            when '/' then
  67.           state := 4;
  68.            else
  69.           state := 8;
  70.            end;
  71.         when 3 then
  72.            -- Waiting end of integer or / of fraction :
  73.            inspect
  74.           c
  75.            when ' ', '%T' then
  76.            when '/' then
  77.           state := 4;
  78.            else
  79.           state := 8;
  80.            end;
  81.         when 4 then
  82.            -- Inside a fraction after / :
  83.            inspect
  84.           c
  85.            when ' ', '%T' then
  86.            when '0' .. '9' then
  87.           state := 5;
  88.            else
  89.           state := 8;
  90.            end;
  91.         when 5 then
  92.            -- Inside denominator :
  93.            inspect
  94.           c
  95.            when ' ', '%T' then
  96.           state := 6;
  97.            when '0' .. '9' then
  98.            else
  99.           state := 8;
  100.            end;
  101.         when 6 then
  102.            -- After denominator :
  103.            inspect
  104.           c
  105.            when ' ', '%T' then
  106.            else
  107.           state := 8;
  108.            end;
  109.         end;
  110.         -- state = 7 : end.
  111.         -- state = 8 : error.
  112.         i := i + 1;
  113.         if i <= s.count then
  114.            c := s.item(i);
  115.         end;
  116.      end;
  117.      -- Setting `Result' :
  118.      inspect
  119.         state
  120.      when 2, 3, 5, 6, 7 then
  121.         Result := true;
  122.      else
  123.      end;
  124.       end;
  125.  
  126.  
  127.    from_integer(n: INTEGER): NUMBER is
  128.      -- Uses value `n' to create a new NUMBER.
  129.       do
  130.      if (n = Minimum_integer)  then
  131.         !LARGE_NEGATIVE_INTEGER!Result.make_smaller(0);
  132.          else
  133.         !SMALL_INTEGER!Result.make(n);
  134.      end;
  135.       ensure
  136.      Result.to_integer = n
  137.       end;
  138.    
  139.    from_string(s: STRING): NUMBER is
  140.      -- Uses contents of `s' to create a new NUMBER.
  141.       require
  142.      is_number(s)
  143.       local
  144.      i: INTEGER;
  145.      num, den: ABSTRACT_INTEGER;
  146.      nb_is_negative: BOOLEAN;
  147.      length, first, last, base: INTEGER;
  148.      power: ABSTRACT_INTEGER;      
  149.       do
  150.      i := s.index_of('/');
  151.      if (i = s.count + 1) then        
  152.         nb_is_negative := false;
  153.         if s.first.is_equal('-') then
  154.            nb_is_negative := true;
  155.            s.remove_first(1);
  156.         elseif s.first.is_equal('+') then
  157.            s.remove_first(1);
  158.         end;
  159.         from
  160.            length := i.Maximum_integer.to_string.count - 1;
  161.            !SMALL_INTEGER!Result.make(0);        
  162.            last := s.count;
  163.            power ?= Result.one;
  164.            check
  165.           power /= Void;
  166.            end;
  167.            base := 10^length;
  168.         until
  169.            last <= 0
  170.         loop
  171.            first := last - length;
  172.            if first < 0 then
  173.           first := 0;
  174.            end;
  175.            Result := Result + ( power @* s.substring(first+1, last).to_integer );
  176.            power ?= power @* base;  
  177.            check
  178.           power /= Void;
  179.            end;
  180.            last := first;
  181.         end;
  182.         if nb_is_negative then
  183.            Result := -Result;
  184.         end;     
  185.      else     
  186.         num ?= from_string( s.substring(1, i - 1) );        
  187.         den ?= from_string( s.substring(i +1, s.count ) );
  188.         check
  189.            num /= Void;
  190.            den /= Void;
  191.         end;
  192.         if (num \\ den).same_as( num.zero ) then 
  193.            Result := num / den;
  194.         else
  195.            if num.is_integer and then den.is_integer then
  196.           !SMALL_FRACTION!Result.make_from_integer(num.to_integer, den.to_integer);
  197.            else
  198.           nb_is_negative := num.is_negative xor den.is_negative;
  199.           num ?= num.abs;
  200.           den ?= den.abs;
  201.           check
  202.              num /= Void;
  203.              den /= Void;
  204.           end;
  205.           !LARGE_FRACTION!Result.make(num, den, nb_is_negative);
  206.            end;
  207.         end;
  208.      end;
  209.       ensure
  210.      Result /= Void
  211.       end; 
  212.    
  213.    from_input_stream(input: INPUT_STREAM ): NUMBER is
  214.      -- Create a number from a file or standard input
  215.       require
  216.      input.is_connected
  217.       local
  218.      string: STRING;
  219.       do
  220.      if not( input.end_of_input ) then
  221.         !!string.make(0);
  222.         input.read_line_in( string );
  223.         Result := from_string( string );
  224.      end;
  225.       end;
  226.  
  227. end -- NUMBER_TOOLS
  228.  
  229.  
  230.  
  231.  
  232.  
  233.  
  234.  
  235.  
  236.